<?php

namespace App\Middlewares;

use App\Exceptions\ParamException;
use Base\BaseController;
use Base\BaseException;
use Base\MiddlewareInterface;
use EasySwoole\Bridge\Exception;
use EasySwoole\Http\AbstractInterface\Controller;
use EasySwoole\Http\Request;

class ValidateParamMiddleware implements MiddlewareInterface
{
    public static $commonRule = [];

    /**
     * 参数验证方法
     * @param BaseController $controller
     * @throws ParamException
     * @throws \ReflectionException
     */
    public static function handle(BaseController &$controller)
    {
        $path = $controller->request()->getUri()->getPath();
        $pathArr = explode('/', $path);
        $pathArrWithoutFunction = $pathArr;
        $functionName = $pathArrWithoutFunction[count($pathArrWithoutFunction) - 1];
        unset($pathArrWithoutFunction[count($pathArrWithoutFunction) - 1]);
        $controllerName = 'App\\HttpController\\' . implode('\\', $pathArrWithoutFunction);
        $ref = new \ReflectionClass($controllerName);
        $methodRef = $ref->getMethod($functionName);
        $doc = $methodRef->getDocComment();

        $requestParam =array_merge(
            $controller->request()->getParsedBody(),
            $controller->request()->getQueryParams()
        );;
        foreach (explode("\n", $doc) as $line) {
            if (stripos($line, "Param") !== false) {
                $_a = strpos($line, '@Param') + 6;
                $_b = strpos($line, "{");
                $_name = trim(substr($line, $_a, $_b - $_a));
                $_value = substr($line, $_b);
                $_rule = json_decode($_value, true);
                $controller->params[$_name] = self::validateByrule($_name, $_rule, $requestParam);
            }
        }

        foreach (self::$commonRule as $_name => $_rule) {
            $controller->params[$_name] = self::validateByrule($_name, $_rule, $requestParam);
        }
    }

    /**
     * 参数验证方法
     * @param $name
     * @param $rule
     * @param $requestParam
     * @return bool|false|int|mixed|string|null
     * @throws ParamException
     */
    public static function validateByrule($name, $rule, $requestParam)
    {
        $value = $requestParam[$name] ?? null;
        if (isset($rule['require']) && $rule['require'] === true) {
            if (is_null($value)) {
                throw new ParamException("缺少参数 {$name} {$rule['desc']}");
            }
        } else {
            $value = $value ?? $rule['default'] ?? null;
        }

        switch (isset($rule['format']) && $rule['format']) {
            case 'int': $value = (int)$value; break;
            case 'string': $value = (string)$value; break;
            case 'json2arr': $value = json_decode($value, true) ?? $value; break;
            case 'arr2json': $value = json_encode($value) ?? $value; break;
            case 'bool': $value = $value ? true : false; break;
        }

        return $value;
    }
}
